home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-12-14 | 12.9 KB | 253 lines | [TEXT/EDIT] |
- Material extracted from the TI Scheme Language Reference Manual
- with permission of the publisher
- Copyright 1985 Texas Instruments Incorporated
-
- [If you print this documentation or copy it onto another disk, be sure to
- include the above copyright and credit notice.]
-
- [The user-contributed implementation of SCOOPS that is distributed with
- MacScheme may not support all the features described in this documentation.
- We have changed the TI documentation only in places that obviously did not
- apply to the MacScheme version. Our omissions are indicated by ellipses,
- and our additions by square brackets -- Semantic Microsystems.]
-
- SCOOPS is an object-oriented programming system for TI Scheme based on
- first-class environments and on multiple and dynamic inheritance. Although
- it is similar in concept and syntax to the object-oriented paradigms of the
- LOOPS (2) and Flavors (25) systems, the implementation of SCOOPS relies
- heavily on the features of the Scheme language....
-
- OVERVIEW: The object-oriented programming world consists of objects, which
- represent abstract entities. An object is comprised of variables, which
- determine the local state of the object, and methods, which define the
- object's behavior. Higher levels of abstraction are built up through
- inheritance; that is, higher level classes of objects may inherit the
- properties of other classes. Large systems can thus be divided naturally
- into coherent parts that can be developed and maintained separately.
- Programmers can also avoid the specification of redundant information.
-
- The only way to interact with an object or to influence its state is by
- sending a message to it. However, the message passing style need not be
- adhered to internally within an object. Methods may use normal lexical
- scoping and procedure calls to access variables and to invoke other methods
- of the same class. Method definition is, therefore, both convenient and
- efficient.
-
- Before you use any of the SCOOPS facilities, be sure to load the SCOOPS
- environment by entering the following:
-
- (load "scoops.sch")
-
- [SCOOPS requires a 1 Mby Macintosh.]
-
- DEFINING CLASSES: A class contains the description of one or more similar
- objects; an object is an instance of a class. The definition of a class
- consists of class variables, instance variables, methods, and mixins. Class
- variables contain information that is shared by all instances of the class.
- Instance variables are local to each instance and contain information
- specific to that instance. Methods are procedures that determine the
- behavior of instances of the class. A class may inherit the variables and
- methods of other classes through mixins. Inheritance has proven to be a
- useful way to organize information in complex systems.
-
- The following code is an example of class definition in SCOOPS:
-
- (define-class employees
- (classvars (no-of-employees 0))
- (instavars name emp-no manager salary (overtime 0))
- (mixins personal-info education-experience)
- (options (gettable-variables name emp-no no-of-employees)
- settable-variables
- inittable-variables))
-
- The class EMPLOYEES has a class variable, NO-OF-EMPLOYEES, which is
- initialized to zero. It also contains five instance variables, NAME, EMP-NO,
- MANAGER, SALARY, and OVERTIME. This class inherits class variables, instance
- variables, and methods from its mixins, PERSONAL-INFO and
- EDUCATION-EXPERIENCE.
-
- Methods are generated automatically for gettable and settable variables. The
- inittable variables can be given initial values when an instance of a class
- is created. In the class EMPLOYEES, all the variables are settable and
- inittable, while only NAME, EMP-NO, and NO-of-EMPLOYEES are gettable.
-
- In object-oriented programming systems, it is traditional to allow class
- variables, instance variables, methods, and mixins to be added or deleted
- from the definition of the class at any time. In the current version of
- SCOOPS in PC Scheme, only methods can be added or deleted. Methods do not
- have to be recompiled when the class defintion is changed.
-
- The special form MAKE-INSTANCE is used to create new objects. Since
- instances are not created with names, it is necessary to keep references to
- them in variables or other data structures.
-
- METHODS: Methods are defined for a class with DEFINE-METHOD. If a method by
- a given name already exists, the next definition replaces the existing one.
-
- The following example illustrates the addition of two methods,
- EARNINGS-GREATER-THAN and EARNINGS, to the class EMPLOYEES:
-
- (define-method (employees earnings) ()
- (+ salary overtime))
-
- (define-method (employees earnings-greater-than) (val)
- (if (>? (earnings) val)
- (writeln name emp-no)
- '()))
-
- The method EARNINGS computes an employee's earnings as the sum of OVERTIME
- and SALARY. The method EARNINGS-GREATER-THAN prints the name and employee
- number of the employee if the earnings are greater than a given value. Note
- that methods can refer to instance variables as if they were lexically
- enclosing variables.
-
- An object's methods are invoked by sending a message to the object with the
- SEND special form. However, if a method in a class needs to invoke another
- method in the same class, including methods inherited from mixins, it may
- call the other method directly as a procedure. This call is illustrated in
- the previous example, where the method EARNINGS-GREATER-THAN calls EARNINGS,
- another method in the same class, as a procedure.
-
- VARIABLES: An object contains two kinds of variables: class variables and
- instance variables. Class variables contain information that is shared by
- all objects of the same class. Instance variables are local to each object
- and contain the object's local state.
-
- Within an object, these variables may be treated as ordinary lexical
- variables. This treatment is illustrated in the example in the previous
- chapter, where the method EARNINGS adds the values of the instance variables
- SALARY and OVERTIME.
-
- If the variables have been defined with the option GETTABLE-VARIABLES,
- methods to access their values are generated automatically. The names of
- these methods are constructed by prefixing the names of the variables with GET-. For example, in the class EMPLOYEES in the first example, the
- variables NAME, EMP-NO, and NO-OF-EMPLOYEES are gettable. The value of a
- gettable variable is obtained by sending a message such as (SEND EMP1
- GET-NAME) to an instance. Similarly, for settable variables, the names of
- the methods are prefixed with SET-, and the value of a settable variable may
- be modified by sending a message such as (SEND EMP1 SET-SALARY 4000) to an
- instance.
-
- The values of gettable class variables also may be accessed or set through
- the class itself without referring to an instance of the class. The special
- forms GETCV and SETCV get and modify the value of a class variable,
- respectively.
-
- ACTIVE VALUES: Active values [2] are used to trigger procedure invocations
- whenever the value of a variable is accessed or updated. Currently, only
- instance variables can have active values. An instance variable is given an
- active value with the special form (ACTIVE initial-value getfn setfn).
-
- The keyword ACTIVE informs the system that this is an active value. The
- procedure getfn is invoked whenever the value of the variable is accessed,
- and the procedure setfn is invoked whenever the value of the variable is
- modified. The procedures getfn and setfn may be external procedures, methods
- in the same class, or #F, if no procedure is to be specified.
-
- Variables with active values are both gettable and settable, and access and
- update methods are generated automatically for them.
-
- To trace references to an instance variable POSITION, you could define
- POSITION as follows:
-
- (define-class shipn
- (instvars (position (active 0 traceget traceset)) ...)
- ...)
-
- Whenever the value POSITION is accessed, the current value is passed to
- TRACEGET, and the value returned from TRACEGET is returned as the value of
- POSITION. Whenver a value is assigned to the variable POSITION, TRACESET is
- invoked with the new value, and POSITION is set to the value returned from
- TRACESET.
-
- Active values may be nested to an arbitrary depth by specifying another
- active value as the initial-value of an active value:
-
- (active (active initial-value getfn1 setfn1) getfn2 setfn2)
-
- Whenever the value of the variable bound to this active value is set, the
- setfn procedures are invoked in order from the outermost to the innermost.
- Likewise, whenever the value of the variable is accessed, the getfn
- procedures are invoked from the innermost to the outermost.
-
- SCOOPS also provides a way to access or modify active values without invoking
- the getfn and setfn procedures.
-
- Within an object, the value of a class or instance variable can be accessed
- in two ways---as a lexical variable and with its SET- and GET- methods. The
- simplest way is to access it as a lexical variable, using SET!, for example.
- When an active value is modified in this manner, its setfn procedures are not
- invoked.
-
- The other way to modify an active value is with a procedure call, such as
- (SET-POSITION 10). This call invokes the setfn procedures for the active
- value in the manner described previously. Similarly, if POSITION is simply
- referenced as a lexical variable, the current value is returned, and the
- getfn procedures are not invoked. However, if the GET-POSITION procedure is
- used to retrieve the value, the getfn procedures in the active value are
- invoked in order.
-
- INHERITANCE: Inheritance is used to build higher levels of abstractions.
- Large systems can be organized through an inheritance structure of classes,
- thus permitting a modular design and avoiding the specification of redundant
- information.
-
- In SCOOPS, an inheritance structure is built by "mixing in" other classes to
- form an acyclic directed graph. Classes that are made to be components of
- other classes in this way are called mixins. A class inherits the class
- variables, instance variables, and methods from its component classes. The
- order in which the component classes are combined determines which variables
- and methods are inherited when naming conflicts arise. The inheritance
- graph is searched in depth-first order, omitting any nodes that have been
- visited previously. For example, if CLASS1 has mixins CLASS2 and CLASS3,
- CLASS2 has mixins CLASS4 and CLASS5, and CLASS3 has mixins CLASS4 and CLASS6,
- the order in which the classes are combined is CLASS1, CLASS2, CLASS4,
- CLASS5, CLASS3, CLASS6.
-
- The set of class variables and instance variables of a class is the union of
- class variables and instance variables of its component classes. However,
- the class variables that CLASS1 inherits from its component classes are
- shared by all instances of CLASS1 but are not shared by instances of its
- component classes.
-
- Methods also are combined in a simple manner. If two classes contain a method
- with the same name, the method whose class is closer to the root in the
- depth-first order is inherited. Methods may be added or deleted at any time.
- The changes made to any classes are propagated throughout the inheritance
- structure.
-
- The actual inheritance structure for a class is not contructed until the
- class is compiled with the COMPILE-CLASS operation. This operation is
- performed automatically the first time MAKE-INSTANCE is used to create an
- object that is an instance of the class. COMPILE-CLASS builds the
- inheritance graph for a class by inspecting each of its mixins. Until a
- class is "compiled" in this way, the procedure DESCRIBE is unable to describe
- completely all of its class variables, instance variables, and mixins.
-
- This use of the term "compile" should not be confused with the compilation
- step of the Scheme evaluator, EVAL. The term describes the process of
- collecting the pieces of the class definition into one place. Compiling a
- class with COMPILE-CLASS does not prohibit further method definitions for the
- class, and adding method definitions to a class does not require that it be
- recompiled.
-
- The order in which the classes in the inheritance graph are compiled with
- COMPILE-CLASS is immaterial. Compiling a class does not automatically cause
- its mixins to be compiled, although the full graph containing them as nodes
- is built in order to collect all the components of the compiled class. Once
- a mixin has been added to the inheritance graph in this way, the procedure
- DESCRIBE is able to describe all its components, although it may not have
- been compiled itself.
-
- Although a class is automatically compiled the first time MAKE-INSTANCE is
- used to create an instance of the class, it frequently is desirable to
- compile the class explicitly. For example, when a source file containing
- class definitions is to be compiled into object form with COMPILE-FILE,
- explicit calls to COMPILE-CLASS cause the class to be compiled and the
- inheritance structure to be constructed at the time the file is compiled.
- Otherwise, the class is compiled every time the file is loaded and the first
- MAKE-INSTANCE occurs.
-
- Note that all the mixins of a class need to be defined before the class is
- compiled or its first instance object is created.
-